package com.shengqin.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.URLUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shengqin.annotations.OperaLog;
import com.shengqin.calculate.data.ErrorLogModel;
import com.shengqin.common.pojo.CommonPage;
import com.shengqin.common.pojo.CommonResult;
import com.shengqin.config.CommonException;
import com.shengqin.config.model.TestProjectConfig;
import com.shengqin.entity.*;
import com.shengqin.enums.BusinessType;
import com.shengqin.listeners.TestResultDataListener;
import com.shengqin.listeners.TestResultLineListener;
import com.shengqin.pojo.exam.PublicityQueryParam;
import com.shengqin.pojo.plan.result.ImportResultLineParam;
import com.shengqin.pojo.plan.result.ImportTestResultParam;
import com.shengqin.pojo.plan.result.ScoreQueryResult;
import com.shengqin.pojo.summary.SummaryModel;
import com.shengqin.pojo.summary.SummaryQueryParam;
import com.shengqin.service.IPlanService;
import com.shengqin.service.IPlanStudentService;
import com.shengqin.service.ISummaryResultService;
import com.shengqin.service.ITestResultService;
import com.shengqin.utils.FreemarkerUtil;
import com.shengqin.utils.GradeUtil;
import com.shengqin.utils.PdfUtil;
import com.shengqin.utils.QRCodeUtil;
import freemarker.template.TemplateException;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("admin/v1/testResult")
@Slf4j
public class TestResultController {

    @Resource
    private ITestResultService testResultService;
    @Resource
    private IPlanService planService;
    @Resource
    private IPlanStudentService planStudentService;
    @Resource
    private TestProjectConfig testProjectConfig;
    @Resource
    private ISummaryResultService summaryResultService;

    @Operation(description = "体测集体公示导出")
    @PostMapping("exportPublic")
    public void exportPublic(@RequestBody PublicityQueryParam queryPageParam, HttpServletResponse response) throws IOException {
        log.info("体测集体公示导出入参 {}", JSON.toJSONString(queryPageParam));

        try {
            response.reset();
            response.setContentType("application/pdf");
            String filename = System.currentTimeMillis() + ".pdf";
            response.addHeader("Content-Disposition", "inline; filename=" + URLUtil.encode(filename, CharsetUtil.CHARSET_UTF_8));

            List<PlanStudent> planStudents = planStudentService.queryByPlanIdAndStudyCodes(queryPageParam.getPlanId(),queryPageParam.getStudyCodeList());
            List<SummaryResult> summaryResults = summaryResultService.queryStudyCodesAndPlanId(queryPageParam.getStudyCodeList(),queryPageParam.getPlanId());
            List<TestResult> testResultList = testResultService.listByPlanIdAndStudyCodes(queryPageParam.getPlanId(),queryPageParam.getStudyCodeList());
            Map<String,List<TestResult>> testResultMap = testResultList.stream().collect(Collectors.groupingBy(TestResult::getStudyCode));
            Map<String,SummaryResult> summaryResultMap = summaryResults.stream().collect(Collectors.toMap(SummaryResult::getStudyCode,item -> item));

            Map<String,Object> resultMap = new HashMap<>();
            List<String> htmlStrList = new ArrayList<>();
            TestResult testResult = testResultList.get(0);
            Integer planId = testResult.getPlanId();
            Plan plan = planService.getById(planId);
            Map<String,Object> data = new HashMap<>();
            data.put("planName",plan.getName());
            data.put("gradeName", GradeUtil.getGradeName(testResult.getGradeId()));

            List<JSONObject> testItems = new ArrayList<>();

            Map<Integer,List<PlanStudent>> gradeStudentMap = planStudents.stream().collect(Collectors.groupingBy(PlanStudent::getGradeId));
            gradeStudentMap.forEach((gradeId,students) -> {
                List<PlanStudent> sortList = students.stream().sorted(
                        Comparator.comparing(PlanStudent::getGradeName)
                                .thenComparing(PlanStudent::getClassesName)).collect(Collectors.toList());
                sortList.forEach(item -> {
                    JSONObject testItem = new JSONObject();
                    testItem.put("classesName", item.getClassesName());
                    testItem.put("name", item.getName());
                    testItem.put("sex", item.getSex());
                    testItem.put("studyCode", item.getStudyCode());
                    List<TestResult> testResults = testResultMap.getOrDefault(item.getStudyCode(), null);
                    List<TestResult> finalTestResultList = new ArrayList<>();
                    if (!CollectionUtils.isEmpty(testResults)) {
                        Map<String, List<TestResult>> finalPrjResultMap = testResults.stream().collect(Collectors.groupingBy(TestResult::getPrjName));

                        String prjNames = testProjectConfig.getProjectMap().get(gradeId + "_" + item.getSex());
                        List<String> projectNameList = Arrays.asList(prjNames.split(","));
                        projectNameList.forEach(projectName -> {
                            String prjName = projectName;
                            if (prjName.equalsIgnoreCase("身高体重")) {
                                List<TestResult> whResults = finalPrjResultMap.getOrDefault(prjName, null);
                                if (CollectionUtils.isEmpty(whResults)) {
                                    prjName = "BMI";
                                }
                            }
                            if (finalPrjResultMap.containsKey(prjName)) {
                                TestResult result = finalPrjResultMap.get(prjName).get(0);
                                finalTestResultList.add(result);
                            } else {
                                TestResult result = new TestResult();
                                result.setResultType("未测试");
                                result.setPrjName(prjName);
                                result.setScore(BigDecimal.ZERO);
                                result.setFinalScore(BigDecimal.ZERO);
                                finalTestResultList.add(result);
                            }
                        });
                        testItem.put("testResultList", finalTestResultList);
                        testItem.put("summaryResult", summaryResultMap.getOrDefault(item.getStudyCode(),new SummaryResult()));
                        testItems.add(testItem);
                    }
                });
            });


            data.put("testItems",testItems);
            data.put("showScore",queryPageParam.getShowScore());
            data.put("showLevel",queryPageParam.getShowLevel());
            resultMap.put("data",data);
            try {
                String templateName = "batch_public_custom_dy.ftl";
                if(queryPageParam.getTemplateStyle().equals("custom")){
                    templateName = "batch_public_custom_dy.ftl";
                }
                String html = FreemarkerUtil.loadTemplateFromFile(templateName,resultMap);
                htmlStrList.add(html);
            } catch (IOException | TemplateException e) {
                throw new RuntimeException(e);
            }

            byte[] pdfOut = PdfUtil.html2Pdf(htmlStrList);

            OutputStream out = response.getOutputStream();
            out.write(pdfOut);
            out.close();
        } catch (Exception e){
            log.error("体测导出成绩公示报错",e);
        }
    }

    /**
     * 查询单人成绩公示（体测）
     */
    @PostMapping("queryScoreResult")
    public CommonResult<ScoreQueryResult> queryScoreResult(@RequestBody ScoreQueryResult scoreQueryResult){
        return CommonResult.data(testResultService.queryScoreResult(scoreQueryResult));
    }

    @PostMapping("retry")
    public CommonResult<Boolean> retry(@RequestBody ErrorLogModel errorLogModel){
        return CommonResult.data(testResultService.retry(errorLogModel.getId()));
    }

    @PostMapping("calculate")
    public CommonResult<Boolean> calculate(@RequestBody TestResult queryParam){
        return CommonResult.data(testResultService.calculate(queryParam));
    }

    @PostMapping("updateParentPlanTest")
    public CommonResult<Boolean> updateParentPlanTest(@RequestBody TestResult queryParam){
        return CommonResult.data(testResultService.updateParentPlanTest(queryParam));
    }

    @PostMapping("clearData")
    public CommonResult<Boolean> clearData(@RequestBody TestResult queryParam){
        return CommonResult.data(testResultService.clearData(queryParam));
    }

    @PostMapping("summary")
    public CommonResult<List<SummaryModel>> summary(@RequestBody SummaryQueryParam queryParam){
        return CommonResult.data(testResultService.summary(queryParam));
    }

    @PostMapping("page")
    public CommonResult<Page<TestResult>> getPage(@RequestBody CommonPage<TestResult> queryPage){
        return CommonResult.data(testResultService.getPage(queryPage));
    }

    @Operation(summary = "导入测试成绩文件")
    @PostMapping("importTestData")
    public CommonResult importTestData(@RequestPart("file") MultipartFile file, @RequestParam Integer planId) {
        log.info("导入测试成绩{}", planId);
        try {
            EasyExcel.read(file.getInputStream(), ImportTestResultParam.class, new TestResultDataListener(testResultService,planId)).sheet().doRead();
        } catch (ExcelDataConvertException e) {
            String message = String.format("第%s行，第%s列解析异常，请修改后重新上传", e.getRowIndex() + 1, e.getColumnIndex() + 1);
            throw new CommonException(message);
        } catch (Exception e) {
            throw new CommonException("上传失败，请重试。错误信息：" + e.getMessage());
        }
        return CommonResult.ok().setMsg("导入成功");
    }

    @Operation(summary = "导入已有测试成绩文件")
    @PostMapping("importTestLineData")
    public CommonResult importTestLineData(@RequestPart("file") MultipartFile file, @RequestParam Integer planId) {
        try {
            EasyExcel.read(file.getInputStream(), ImportResultLineParam.class, new TestResultLineListener(testResultService,planId)).sheet().doRead();
        } catch (ExcelDataConvertException e) {
            String message = String.format("第%s行，第%s列解析异常，请修改后重新上传", e.getRowIndex() + 1, e.getColumnIndex() + 1);
            throw new CommonException(message);
        } catch (Exception e) {
            throw new CommonException("上传失败，请重试。错误信息：" + e.getMessage());
        }
        return CommonResult.ok().setMsg("导入成功");
    }

    @PostMapping("delete")
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Boolean> delete(@RequestBody TestResult testResult){
        TestResult result = testResultService.getById(testResult.getId());
        TestResult queryTest = new TestResult();
        queryTest.setStudyCode(result.getStudyCode());
        queryTest.setPlanId(result.getPlanId());
        boolean isOk = testResultService.removeById(testResult.getId());
        if (isOk) {
            testResultService.calculate(queryTest);
        }
        return CommonResult.data(isOk);
    }
}
